package com.ssm.circle.server.service.impl;

import com.github.benmanes.caffeine.cache.Cache;
import com.github.benmanes.caffeine.cache.Caffeine;
import com.ssm.circle.api.enums.IsDeletedFlagEnum;
import com.ssm.circle.api.req.RemoveShareCircleReq;
import com.ssm.circle.api.req.SaveShareCircleReq;
import com.ssm.circle.api.req.UpdateShareCircleReq;
import com.ssm.circle.api.vo.ShareCircleVO;
import com.ssm.circle.server.dao.ShareCircleDao;
import com.ssm.circle.server.entity.po.ShareCircle;
import com.ssm.circle.server.service.ShareCircleService;
import com.ssm.circle.server.utils.LoginUtil;
import lombok.extern.log4j.Log4j2;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.time.Duration;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
import java.util.stream.Stream;

@Service
@Log4j2
public class ShareCircleServiceImpl implements ShareCircleService {

    @Resource
    private ShareCircleDao shareCircleDao;

    private static final Cache<Integer, List<ShareCircleVO>> CACHE = Caffeine.newBuilder()
            .initialCapacity(1) //设置缓存的初始容量为1，会预先分配足够的空间来存储1个键值对，
            .maximumSize(1)
            .expireAfterWrite(Duration.ofSeconds(30))
            .build();

    @Override
    public Boolean saveCircle(SaveShareCircleReq req) {
        ShareCircle circle = new ShareCircle();
        circle.setCircleName(req.getCircleName());
        circle.setIcon(req.getIcon());
        circle.setParentId(req.getParentId());
        circle.setIsDeleted(IsDeletedFlagEnum.UN_DELETED.getCode());
        circle.setCreatedTime(new Date());
        circle.setCreatedBy(LoginUtil.getLoginId());
        CACHE.invalidateAll();
        return shareCircleDao.save(circle);
    }

    @Override
    public ShareCircle getById(Long parentId) {
        return shareCircleDao.getById(parentId);
    }

    @Override
    public Boolean updateCircle(UpdateShareCircleReq req) {
        ShareCircle circle = new ShareCircle();
        circle.setId(req.getId());
        circle.setCircleName(req.getCircleName());
        circle.setIcon(req.getIcon());
        circle.setParentId(req.getParentId());
        circle.setIsDeleted(IsDeletedFlagEnum.UN_DELETED.getCode());
        circle.setUpdateTime(new Date());
        circle.setUpdateBy(LoginUtil.getLoginId());
        CACHE.invalidateAll(); //清空缓存
        return shareCircleDao.updateCircle(circle);
    }

    @Override
    public Boolean removeCircle(RemoveShareCircleReq req) {
        ShareCircle circle = new ShareCircle();
        circle.setId(req.getId());
        circle.setIsDeleted(IsDeletedFlagEnum.DELETED.getCode());
        CACHE.invalidateAll();
        return shareCircleDao.updateCircle(circle);
    }

    @Override
    public List<ShareCircleVO> listResult() {
        List<ShareCircleVO> res = CACHE.getIfPresent(1); //key为1
        return Optional.ofNullable(res).orElseGet(() -> {
            List<ShareCircle> list = shareCircleDao.selectAll();
            List<ShareCircle> parentList = list.stream().filter(item -> item.getParentId() == -1).collect(Collectors.toList());
            Map<Long, List<ShareCircle>> chardMap = list.stream().collect(Collectors.groupingBy(ShareCircle::getParentId));
            List<ShareCircleVO> parentVOList = parentList.stream().map(item -> {
                ShareCircleVO vo = new ShareCircleVO();
                vo.setId(item.getId());
                vo.setCircleName(item.getCircleName());
                vo.setIcon(item.getIcon());
                List<ShareCircle> shareCircles = chardMap.get(item.getId());
                if(CollectionUtils.isEmpty(shareCircles)) {
                    vo.setChildren(Collections.emptyList());
                } else {
                    List<ShareCircleVO> shareCircleVOStream = shareCircles.stream().map(e -> {
                        ShareCircleVO cVo = new ShareCircleVO();
                        cVo.setId(e.getId());
                        cVo.setCircleName(e.getCircleName());
                        cVo.setIcon(e.getIcon());
                        cVo.setChildren(Collections.emptyList());
                        return cVo;
                    }).collect(Collectors.toList());
                    vo.setChildren(shareCircleVOStream);
                }
                return vo;
            }).collect(Collectors.toList());
            CACHE.put(1, parentVOList);
            return parentVOList;
        });
    }


}
